﻿/*
 * protocolcontrolorbase.hpp
 *
 *  Created on: 2017年4月14日
 *      Author: work
 */

#ifndef _DM_OS_PROTOCOL_PROTOCOLCONTROLORBASE_HPP_
#define _DM_OS_PROTOCOL_PROTOCOLCONTROLORBASE_HPP_

#include <dm/export.hpp>

#ifndef DM_API_OS_PROTOCOL
#define DM_API_OS_PROTOCOL DM_API_IMPORT
#endif

#include <dm/protocol/protocolbase.hpp>

#include <dm/os/ascom/timer.hpp>
#include <dm/os/ascom/device.hpp>
#include <dm/os/com/device.hpp>
#include <boost/signals2/signal.hpp>

namespace dm{
namespace os{
namespace protocol{

class DM_API_OS_PROTOCOL CProtocolControlor{
public:
	typedef dm::protocol::CProtocolBase protocol_t;

	typedef protocol_t::frame_t frame_t;
	typedef protocol_t::interval_t interval_t;

	typedef frame_t::txbuf_t txbuf_t;
	typedef frame_t::rxbuf_t rxbuf_t;
	typedef rxbuf_t::pos_t pos_t;

	typedef dm::os::ascom::CDevice device_t;

	typedef dm::os::ascom::CTimer timer_t;

	typedef void(f_void_t)();
	typedef boost::signals2::signal<f_void_t> sig_void_t;

	sig_void_t sig_devDisconnected;

	CProtocolControlor( com::ios_t& ios );
	virtual ~CProtocolControlor();

	bool setProtocol( protocol_t* protocol );

	void setDevice( device_t* dev );

	inline const bool& ifAutoConnect()const{
		return m_autoConnect;
	}

	inline void setAutoConnect( const bool& s=true ){
		m_autoConnect = s;
	}

	inline void setAutoConnectDelay( int delay ){
		m_autoConnectDelay = delay;
	}

	inline void setAutoConnectDelayDelta( int delta ){
		m_autoConnectDelayDelta = delta;
	}

	inline void setAutoConnectDelayMaxTime( int max ){
		m_autoConnectDelayMaxTimes = max;
	}

	bool isDeviceSetted()const;

	bool openDevice();
	bool closeDevice();

	bool onConnected();
	void onConnectedFail();
	void onDisconnected();
	void onRx( const dm::uint8* buf,const size_t& len );
	void onRxFail();
	void onTxFail();
	void onTxed();

	void onTimeUp();

	inline const dm::uint16& getConnectCnt()const{
		return m_connectCnt;
	}

	inline const dm::uint16& getConnectCntMax()const{
		return m_connectCntMax;
	}

	inline void setConnectCntMax( dm::uint16 cntMax ){
		m_connectCntMax = cntMax;
	}

	/**
	 * 控制器是否退出
	 * @return
	 * - true 退出。后续不应该再执行本控制器了。
	 * - false 正常，不需要退出
	 */
	bool isExiting()const;

	void setFlag_exit();

protected:
	bool sendFrame();

	inline txbuf_t& txBuf(){
		return m_txBufSending==1?m_txBuf2:m_txBuf1;
	}

protected:
	/**
	 * 通信设备
	 */
	device_t * m_dev;

	/**
	 * 是否自动连接
	 */
	bool m_autoConnect;

	int m_autoConnectDelay;	// 延时连接时长 秒

	int m_autoConnectDelayTimes;	// 延时连接增量计数
	int m_autoConnectDelayDelta;	// 延时连接时间增量 秒
	int m_autoConnectDelayMaxTimes;	// 延时连接增量最多次数

	/**
	 * 连接计数
	 * 每次有新的连接时，本计数会增加
	 */
	dm::uint16 m_connectCnt;

	/**
	 * 连接计数最大值
	 * 如果连接次数超过本值，则程序退出。
	 * - 0 不会退出
	 */
	dm::uint16 m_connectCntMax;

	int m_txBufSending;	//!< 当前发送正在使用的缓冲区 0: 无 1：1号 2：2号
	/**
	 * 发送缓冲区1
	 */
	txbuf_t m_txBuf1;

	/**
	 * 发送缓冲区2
	 */
	txbuf_t m_txBuf2;

	/**
	 * 接收缓冲区
	 */
	rxbuf_t m_rxBuf;
	pos_t m_rxPos;

	/**
	 * 刷新定时器
	 */
	timer_t m_timer;

	protocol_t* m_protocol;

	/**
	 * 标志
	 * 目前支持退出标志
	 */
	dm::uint8 m_flags;
};

}
}
}

#endif /* INCLUDE_DM_OS_PROTOCOL_PROTOCOLCONTROLORBASE_HPP_ */
